/*
 * Copyright 2008 Carnegie Mellon University
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, 
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package edu.cmu.lti.sepia.api.processor;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.json.JSONObject;

import edu.cmu.lti.sepia.api.json.JsonAction;
import edu.cmu.lti.sepia.data.db.IRJudgmentResultDAO;
import edu.cmu.lti.sepia.data.db.PoolDAO;
import edu.cmu.lti.sepia.data.db.SQL;
import edu.cmu.lti.sepia.data.db.TopicDAO;
import edu.cmu.lti.sepia.infra.eval.model.IRJudgmentResult;
import edu.cmu.lti.sepia.infra.eval.model.IRJudgmentResults;
import edu.cmu.lti.sepia.infra.eval.model.IRJudgmentUnit;
import edu.cmu.lti.sepia.infra.topic.model.Topic;
import edu.cmu.lti.sepia.task.nlp.TextProcessor;
import edu.cmu.lti.sepia.task.retrieval.Retriever;
import edu.cmu.lti.sepia.util.ExceptionUtil;
import edu.cmu.lti.sepia.util.ServletUtil;

/**
 * The processor for evaluating retrieval results.
 *
 */
public class IREvalProcessor extends AbstractProcessor {

  @Override
  public JSONObject process(SQL sql, JsonAction action, HttpServletRequest request) {
    ServletUtil servletUtil = new ServletUtil(request);

    String sortingCriteria = servletUtil.readString("sortingCriteria", "score");
    String taskNameShort = servletUtil.readString("taskNameShort", "");
    String trgLang = servletUtil.readString("trgLang", "");
    int poolId = servletUtil.readInt("poolId", -1);
    String externalId = servletUtil.readString("externalId", "");
    String docId = servletUtil.readString("docId", "");
    String judgment = servletUtil.readString("judgment", "");
    String evidence = servletUtil.readString("evidence", "");
    int userId = servletUtil.readInt("userId", -1);
    int index = servletUtil.readInt("index", -1);
    int time = servletUtil.readInt("time", -1);

    JSONObject json = new JSONObject();
    try {
      json.put("msg", "succeeded");

      if (action.equals(JsonAction.IREvalPools)) {
        json = PoolDAO.getPoolJson(PoolDAO.getPools(sql, taskNameShort, true));
      } else if (action.equals(JsonAction.IREvalTopics)) {
        List<Topic> topics = TopicDAO.getTopics(sql, taskNameShort, null, -1);
        TopicDAO.generateExternalIds(topics, trgLang, 4);
        TopicDAO.removeUnselected(topics);
        json = TopicDAO.convertTopics(topics);
      } else if (action.equals(JsonAction.IREvalDocList)) {
        IRJudgmentResults results = IRJudgmentResultDAO.findResultsByPoolAndTopic(sql,
                taskNameShort, poolId, externalId, userId);
        if (sortingCriteria.equals("docid")) {
          Collections.sort(results, new Comparator<IRJudgmentResult>() {
            public int compare(IRJudgmentResult r1, IRJudgmentResult r2) {
              String val1 = (String) r1.getDocId();
              String val2 = (String) r2.getDocId();
              return val1.compareTo(val2);
            }
          });
        } else if (sortingCriteria.equals("judgment")) {
          // two level sorting
          Collections.sort(results, new Comparator<IRJudgmentResult>() {
            public int compare(IRJudgmentResult r1, IRJudgmentResult r2) {
              Integer val1 = r1.isEvaluatedByOthers() ? 1 : 0;
              Integer val2 = r2.isEvaluatedByOthers() ? 1 : 0;
              return val1.compareTo(val2) * (-1);
            }
          });
          Collections.sort(results, new Comparator<IRJudgmentResult>() {
            public int compare(IRJudgmentResult r1, IRJudgmentResult r2) {
              String val1 = (String) r1.getJudgment();
              String val2 = (String) r2.getJudgment();
              return val1.compareTo(val2) * (-1);
            }
          });
        } else { // by pool weight
          Collections.sort(results, new Comparator<IRJudgmentResult>() {
            public int compare(IRJudgmentResult r1, IRJudgmentResult r2) {
              Integer val1 = r1.getJudgmentId();
              Integer val2 = r2.getJudgmentId();
              return val1.compareTo(val2);
            }
          });
        }
        json = IRJudgmentResultDAO.getIRJudgmentResults(results);
      } else if (action.equals(JsonAction.IREvalUpdate)) {
        IRJudgmentUnit u = new IRJudgmentUnit(-1, -1, externalId, docId, 0D);
        IRJudgmentResult result = new IRJudgmentResult(u, userId, judgment, evidence, time);
        IRJudgmentResultDAO.updateResult(sql, taskNameShort, result);
      } else if (action.equals(JsonAction.IREvalGetDoc)) {
        String content;
        try {
          content = Retriever.getInstance(taskNameShort).getDocumentFromExternalId(docId);
          if (content == null)
            throw new NullPointerException("Make sure index exists");
        } catch (Exception e) {
          content = ExceptionUtil.exceptionToString(e);
          // content = "<DOC>\n<TEXT>\nHELLO オランダのハーグ事件はなかなか。ハーグ事件です。\n\n "+
          // new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Calendar.getInstance().getTime())+
          // "\n</TEXT>\n</DOC>\n";
        }
        content = content.replaceAll("<([/]?(?:TEXT|DOCNO|DOC|HEADLINE|DATE))>", "&lt;$1&gt;");
        content = content.replaceAll("\n", "<br>");
        content = content.replaceAll("'", "\\\'");
        content = content.replaceAll("^(<br>)+", "");
        content = TextProcessor.unsegment(content);
        json = new JSONObject();
        json.put("document", content);
        json.put("index", index);
      }
    } catch (Exception e) {
      e.printStackTrace();
      try {
        json.put("exception", ExceptionUtil.exceptionToString(e));
      } catch (Exception e2) {
        e2.printStackTrace();
      }
    }
    return json;
  }

}
